/*
  关于访问:
    访问 vuex 可以使用 this.$store 来访问,但这仅仅针对于组件而言(因为我们将 store 挂载到 Vue实例的原型链上)
    对于非组件而言,想要访问 vuex 方法有两种:
      1. 导入vue,利用其原型链进行访问import Vue from 'vue' -> Vue.prototype.$store.......
      2. 导入store 直接使用,这里的 store 相当于组件中的 this.$store
    这里我们使用的就是第二种方法,更加简洁
*/
import router from '@/router/index'
import store from '@/store/index'

// 加载进度条组件
import nprogress from 'nprogress'
import 'nprogress/nprogress.css'

// 导航守卫(前置)
router.beforeEach(async(to, from, next) => {
  // 开启进度条
  nprogress.start()
  const whiteList = ['/login', '/404']
  if (store.getters.token) {
    // 判断是否是访问的是登录页
    // 不能从主页直接手动修改地址跳转到登录页
    // 这样操作不会清除 token 会出问题
    if (to.path === '/login') {
      next('/')
    } else {
      // 获取用户资料(判断是否获取过,如果没有获取过才发请求获取资料)
      // 如果不加判断,所有经过这里的请求都会触发获取用户的资料!!!
      if (!store.getters.userId) {
        const { roles: { menus }} = await store.dispatch('user/getUserInfo')
        const filterRoutes = await store.dispatch('permission/filterRoutes', menus)
        // 方式 1. 直接在守卫中写,不在vuex中写
        // const filterRoutes = asyncRoutes.filter(t => menus.indexOf(t.name) > -1)
        // 这里有一个BUG,实际上 asyncRoutes 中的路由已经被加入了,但在加入前 router.options.routes 就已经生成了(这里不是动态的)
        // 参考问答 : https://segmentfault.com/q/1010000015212346
        router.addRoutes([...filterRoutes, { path: '*', redirect: '/404', hidden: true }])
        // store.commit('permission/setRoutes', filterRoutes)
        // console.log(to, to.path)
        // 这里有一个已知的BUG,这里直接next()会导致刷新路由丢失的问题
        // 可以再跳转一次 -> 开门,打开方式不对 -> 再来一次
        return next(to.path === '/404' ? to.redirectedFrom : to.path)
      }
      next()
    }
  } else {
    if (whiteList.includes(to.path)) {
      next()
    } else {
      next('/login')
    }
  }
  // 手动关闭进度条(防止手动在地址栏中访问时无法关闭的问题)
  nprogress.done()
})

// 后置守卫
router.afterEach((to, from, next) => {
  nprogress.done()
})
